package fr.unice.tinytorrent.objects;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
import javax.naming.NamingException;

import fr.unice.tinytorrent.HashValue;
import fr.unice.tinytorrent.TinyTorrent;
import fr.unice.tinytorrent.api.RemoteClient;
import fr.unice.tinytorrent.api.Tracker;

public class TrackerImpl extends UnicastRemoteObject implements Tracker {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	// l'adresse du Server
	private String url;
	// le port
	private int port;
	// pour gerer le fait qu'un Remote Client pour contenir plusieur ressources,
	// on attribut un RemoteClient à une liste de HashValue ( Set<HashValue> )
	private Hashtable<RemoteClient, Set<HashValue>> data;
	private Hashtable<RemoteClient, Set<TinyTorrent>> data1;
	
	
	public TrackerImpl(String url, int port) throws RemoteException, NamingException
	{
		this.url = url;
		this.port = port;
		this.demarrer(this.url, this.port);
		data = new Hashtable<RemoteClient, Set<HashValue>>();
		data1 = new Hashtable<RemoteClient, Set<TinyTorrent>>();
	}
	
	
	
	@Override
	public void register(HashValue resourceHashValue, RemoteClient client) throws RemoteException {
		System.out.println("***********************  Tracker *******************************");
		Set<HashValue> dataList = (Set<HashValue>) data.get(client);
		if(dataList != null)
		{
			dataList.add(resourceHashValue);
			System.out.println("Ressource ajoutée dans le Serveur");
		}
		else
		{
			dataList = new HashSet<HashValue>();
			dataList.add(resourceHashValue);
			data.put(client, dataList);
			System.out.println("Ressource et Client ajoutés dans le Serveur");
		}
		
	}
	
	
	@Override
	public void register(TinyTorrent torrent, RemoteClient client)	throws RemoteException {
		System.out.println("***********************  Tracker *******************************");
		Set<TinyTorrent> dataList = (Set<TinyTorrent>) data1.get(client);
		if(dataList != null)
		{
			dataList.add(torrent);
			System.out.println("Ressource ajoutée dans le Serveur");
		}
		else
		{
			dataList = new HashSet<TinyTorrent>();
			dataList.add(torrent);
			data1.put(client, dataList);
			System.out.println("Ressource et Client ajoutés dans le Serveur");
		}
		
	}
	
	

	@Override
	public void unregister(HashValue resourceHashValue, RemoteClient client) throws RemoteException {
		
		Set<HashValue> dataList= (Set<HashValue>) data.get(client);
		if(dataList != null)
		{
			dataList.remove(client);
		}
		else
			System.out.println("le client n'est pas enregistré dans le server !");
		

	}

	@Override
	public Set<HashValue> findResourceHashValues() throws RemoteException {
		System.out.println("searching ...");
		
		Set<HashValue> resourceHashValues = new HashSet<HashValue>();
		Enumeration<RemoteClient> seeders = data.keys();
		while(seeders.hasMoreElements())
		{
			Set<HashValue> res = new HashSet<HashValue>();
			
			res = ((Set<HashValue>) data.get(seeders.nextElement()));
			for(HashValue h :res)
			{
				resourceHashValues.add(h);
				System.out.println("un Seeder est trouvé");
			}
		}
		
		
		return resourceHashValues;
	}

	@Override
	public Set<HashValue> findResourceHashValues(RemoteClient client) throws RemoteException {
		
		Set<HashValue> dataList= (Set<HashValue>) data.get(client);
		if(dataList != null)
		{
			return dataList;
		}
		return null;
	}

	@Override
	public Set<RemoteClient> findClients(HashValue resourceHashValue) throws RemoteException {
		
		Set<RemoteClient> remoteClients = new HashSet<RemoteClient>();
		Enumeration<RemoteClient> seeders = data.keys();
		while(seeders.hasMoreElements())
		{
			RemoteClient remoteClient = seeders.nextElement();
			Set<HashValue> res = new HashSet<HashValue>();
			res = ((Set<HashValue>) data.get(remoteClient));
			if(res.contains(resourceHashValue))
				remoteClients.add(remoteClient);
			
		}
		return remoteClients;
	}
	
	
	/**
	 * lance le serveur d'une manière dynamique
	 * @param url l'adresse du serveur
	 * @param p le port utilisé
	 */
	private void demarrer(String url, int p)
	{
		try
		{
			Registry r = LocateRegistry.createRegistry(p);
			r.rebind(url, this);	
			System.out.println("Serveur lancé");
		}
		catch(RemoteException e){ e.printStackTrace(); }
		
	
	
	}



	@Override
	public TinyTorrent findTorrent(String resourceName)throws RemoteException {
		
		Enumeration<RemoteClient> seeders = data1.keys();
		while(seeders.hasMoreElements())
		{
			RemoteClient remoteClient = seeders.nextElement();
			Set<TinyTorrent> res = new HashSet<TinyTorrent>();
			res = ((Set<TinyTorrent>) data1.get(remoteClient));
			for(TinyTorrent t :res)
			if(t.getResourceName().contains(resourceName))
				return t;
			
		}
		return null;
	}


}
